/**
 * 从 ast 生成渲染函数
 * @param {*} ast ast 语法树
 * @returns 渲染函数
 */
export default function generate(ast) {
  // 渲染函数字符串形式
  const renderStr = getElement(ast);
  console.log("renderStr ===> ", renderStr);
  // 根据不同的类型 调用不同的处理函数
  // 通过 new Function 将字符串形式的函数变成可执行函数，并用 with 为渲染函数扩展作用域链
  return new Function(`with(this) { return ${renderStr} }`);
}
/**
 * 解析 ast 生成 渲染函数
 * @param {*} ast 语法树
 * @returns {string} 渲染函数的字符串形式
 */
function getElement(ast) {
  // console.log("ast => ", ast);
  const { tag, rawAttr, attrs } = ast;
  // 生成属性 Map 对象，静态属性 + 动态属性
  // rawAttr 是保留的原生的属性 id class 等
  // attr 是处理的 v-bind:title  @click 等动态属性
  const attrObj = { ...rawAttr, ...attrs };

  // 处理子节点，得到一个所有子节点渲染函数组成的数组
  const children = genChildren(ast);
  // 生成处理插槽得处理函数
  if (tag === "slot") {
    return `_t(${JSON.stringify(attrs)}, [${children}])`;
  }
  // debugger
  // console.log("children ==> ", children);
  // 生成 VNode 的可执行方法
  return `_c('${tag}', ${JSON.stringify(attrObj)}, [${children}])`;
}

/**
 * 处理 ast 节点的子节点，将子节点变成渲染函数
 * @param {*} ast 节点的 ast 对象
 * @returns [childNodeRender1, ....]
 */
function genChildren(ast) {
  const ret = [];
  const { children } = ast;

  for (let i = 0; i < children.length; i++) {
    const child = children[i];
    if (child.type === 3) {
      // 文本
      ret.push(`_v(${JSON.stringify(child)})`);
    } else if (child.type === 1) {
      // 节点
      ret.push(getElement(child));
    }
  }

  return ret;
}
